package com.lry.pda.bottom.c.frontend;

import com.lry.pda.bottom.c.backend.type.*;
import lombok.Setter;

import java.util.*;

public class Grammar {

    public static int LP_EXPR_RP_TO_UNARY;
    public static int DECL_TO_DECL_LIST;
    public static int DECL_LIST_COMMA_DECL_TO_DECL_LIST;
    public static int SPECIFIERS_DECL_LIST_TO_DEF;
    public static int NewName_TO_VarDecl;
    public static int NAME_TO_NewName;
    public static int Number_TO_Unary;
    public static int FALSE_TO_Unary;
    public static int TRUE_TO_Unary;

    public static int Name_TO_Unary;
    public static int String_TO_Unary;
    public static int Unary_LB_Expr_RB_TO_Unary;
    public static int Unary_TO_Binary;
    public static int Binary_TO_NoCommaExpr;
    public static int NoCommaExpr_Equal_NoCommaExpr_TO_NoCommaExpr;

    public static int Binary_LShiftOp_Binary_TO_Binary;
    public static int Binary_RShiftOp_Binary_TO_Binary;
    public static int Binary_And_Binary_TO_Binary;
    public static int Binary_OR_Binary_TO_Binary;
    public static int Binary_XOR_Binary_TO_Binary;

    public static int Binary_Star_Binary_TO_Binary;
    public static int Binary_Mod_Binary_TO_Binary;
    public static int Binary_Divop_Binary_TO_Binary;
    public static int Binary_Plus_Binary_TO_Binary;
    public static int Binary_Minus_Binary_TO_Binary;
    public static int Binary_RelOP_Binary_TO_Binary;

    public static int NoCommaExpr_TO_Expr;
    public static int Expr_Semi_TO_Statement;
    public static int LocalDefs_TO_Statement;
    public static int Statement_TO_StmtList;
    public static int StmtList_Statement_TO_StmtList;
    public static int Var_Decl_Init_To_Decl;
    public static int Expr_TO_Test;
    public static int If_Test_Statement_TO_IFStatement;
    public static int IfElseStatement_Else_Statement_TO_IfElseStatement;

    private Map<Integer, Symbols> symbolMap = new HashMap<>();
    private Map<Integer, List<Production>> productionMap = new HashMap<>();
    private TypeSystem typeSystem = TypeSystem.getSelf();

    @Setter
    private LRValueParser parser;

    private static Grammar self;
    int number = 0;

    private Grammar(){

        //变量定义语法
        initVariableGrammar();

        //函数定义语法
        initFuncDefinitionGrammar();

        //结构体语法
        initStructGrammar();

        //函数实现语法
        initFuncGrammar();

        //计算语法
        initComputeGrammar();

        //数组语法
        initArrayGrammar();

        //goto语法
        initGotoGrammar();

        //if else语法
        initIfGrammar();

        //for，while，do while语法
        initLoopGrammar();

        //swatch case语法
        initSwitchGrammar();

        //终结符语法
        addTerminal();
    }


    /**
     *
     * C variable declaration grammar
     * 初始化变量语法
     *
     *  PROGRAM -> EXT_DEF_LIST
     *              | EMPTY
     *
     *  EXT_DEF_LIST -> EXT_DEF_LIST EXT_DEF
     *                  | EMPTY
     *
     *  //long int a,b;
     *  EXT_DEF -> OPT_SPECIFIERS EXT_DECL_LIST  SEMI
     *             | OPT_SPECIFIERS SEMI
     *
     *
     *  EXT_DECL_LIST ->   EXT_DECL
     *                   | EXT_DECL_LIST COMMA EXT_DECL
     *
     *  EXT_DECL -> VAR_DECL
     *
     *  OPT_SPECIFIERS -> SPECIFIERS
     *                   | EMPTY
     *
     *  SPECIFIERS -> TYPE_OR_CLASS
     *                | SPECIFIERS TYPE_OR_CLASS
     *
     *
     *  TYPE_OR_CLASS -> TYPE_SPECIFIER
     *
     *  TYPE_SPECIFIER ->  TYPE
     *
     *  NEW_NAME -> NAME
     *
     *  VAR_DECL -> NEW_NAME
     *              | STAR VAR_DECL
     *
     */
    private void initVariableGrammar() {
        addProduction(true,new Production(0, CTokenType.PROGRAM.ordinal(), Arrays.asList(CTokenType.EXT_DEF_LIST.ordinal()),number++));

        addProduction(true,new Production(0, CTokenType.EXT_DEF_LIST.ordinal(), Arrays.asList(CTokenType.EXT_DEF_LIST.ordinal(),CTokenType.EXT_DEF.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.EXT_DEF.ordinal(), Arrays.asList(CTokenType.OPT_SPECIFIERS.ordinal(),CTokenType.EXT_DECL_LIST.ordinal(),CTokenType.SEMI.ordinal()),number++,v->{
            Symbol symbol = (Symbol)parser.attributeForParentNode;

            TypeLink specifier = (TypeLink)(parser.valueStack.get(parser.valueStack.size() - 3));

            typeSystem.addSpecifier(symbol,specifier);
            typeSystem.addSymbol(symbol, parser.scope);
        }));

        addProduction(false,new Production(0, CTokenType.EXT_DEF.ordinal(), Arrays.asList(CTokenType.OPT_SPECIFIERS.ordinal(),CTokenType.SEMI.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.EXT_DECL_LIST.ordinal(), Arrays.asList(CTokenType.EXT_DECL.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.EXT_DECL_LIST.ordinal(), Arrays.asList(CTokenType.EXT_DECL_LIST.ordinal(),CTokenType.COMMA.ordinal(),CTokenType.EXT_DECL.ordinal()),number++,v->{
            Symbol currentSym = (Symbol)parser.attributeForParentNode;
            Symbol lastSym = (Symbol)parser.valueStack.get(parser.valueStack.size() - 3);
            currentSym.setNext(lastSym);
        }));

        addProduction(false,new Production(0, CTokenType.EXT_DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal()),number++));

        addProduction(true,new Production(0, CTokenType.OPT_SPECIFIERS.ordinal(), Arrays.asList(CTokenType.SPECIFIERS.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.SPECIFIERS.ordinal(), Arrays.asList(CTokenType.TYPE_OR_CLASS.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.SPECIFIERS.ordinal(), Arrays.asList(CTokenType.SPECIFIERS.ordinal(),CTokenType.TYPE_OR_CLASS.ordinal()),number++,v->{
            parser.attributeForParentNode = parser.valueStack.peek();
            Specifier last = ((TypeLink)parser.valueStack.get(parser.valueStack.size() - 2)).getSpecifier();
            Specifier dst = ((TypeLink)parser.attributeForParentNode).getSpecifier();
            last.copy(dst);
        }));

        addProduction(false,new Production(0, CTokenType.TYPE_OR_CLASS.ordinal(), Arrays.asList(CTokenType.TYPE_SPECIFIER.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.TYPE_SPECIFIER.ordinal(), Arrays.asList(CTokenType.TYPE.ordinal()),number++,v->{
            parser.attributeForParentNode = typeSystem.newType(parser.text);
        }));

        NAME_TO_NewName = number;
        addProduction(false,new Production(0, CTokenType.NEW_NAME.ordinal(), Arrays.asList(CTokenType.NAME.ordinal()),number++,v->{
            parser.attributeForParentNode = new Symbol(parser.text,parser.nestingLevel);
        }));

        NewName_TO_VarDecl = number;
        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.NEW_NAME.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.STAR.ordinal(),CTokenType.VAR_DECL.ordinal()),number++,v->{
            typeSystem.addDeclarator((Symbol)parser.attributeForParentNode, Declarator.POINTER);
        }));
    }


    /**
     * production num begin with 15
     * 函数定义:type funName(参数列表);
     *
     * EXT_DEF -> OPT_SPECIFIERS FUNCT_DECL SEMI
     *
     * FUNCT_DECL -> NEW_NAME LP VAR_LIST RP
     *              | NEW_NAME LP RP
     * VAR_LIST ->  PARAM_DECLARATION
     *              | VAR_LIST COMMA PARAM_DECLARATION
     * PARAM_DECLARATION -> TYPE_NT VAR_DECL
     *
     * TYPE_NT -> TYPE_SPECIFIER
     *            | TYPE TYPE_SPECIFIER
     */
    private void initFuncDefinitionGrammar() {
        //函数定义
        addProduction(false,new Production(0, CTokenType.EXT_DEF.ordinal(), Arrays.asList(CTokenType.OPT_SPECIFIERS.ordinal(),CTokenType.FUNCT_DECL.ordinal(),CTokenType.SEMI.ordinal()),number++));

        NEW_NAME_LP_VAR_LIST_RP_TO_FUNCT_DECL = number;
        //带参函数
        addProduction(false,new Production(0, CTokenType.FUNCT_DECL.ordinal(), Arrays.asList(CTokenType.NEW_NAME.ordinal(),CTokenType.LP.ordinal(),CTokenType.VAR_LIST.ordinal(),CTokenType.RP.ordinal()),number++,v->{
            setFunctionSymbol(true);
            Symbol argList = (Symbol)parser.valueStack.get(parser.valueStack.size() - 2);
            ((Symbol)parser.attributeForParentNode).setArgs(argList);
            typeSystem.addSymbol((Symbol)parser.attributeForParentNode, parser.scope);
            //遇到函数定义，变量的scope名称要改为函数名,并把函数参数的scope改为函数名
            parser.scope = ((Symbol)parser.attributeForParentNode).getName();
            Symbol sym = argList;
            while (sym != null) {
                sym.setScope(parser.scope);
                sym = sym.getNext();
            }
        }));

        NEW_NAME_LP_RP_TO_FUNCT_DECL = number;
        //无参函数
        addProduction(false,new Production(0, CTokenType.FUNCT_DECL.ordinal(), Arrays.asList(CTokenType.NEW_NAME.ordinal(),CTokenType.LP.ordinal(),CTokenType.RP.ordinal()),number++,v->{
            setFunctionSymbol(false);
            typeSystem.addSymbol((Symbol)parser.attributeForParentNode, parser.scope);
            //遇到函数定义，变量的scope名称要改为函数名
            parser.scope = ((Symbol)parser.attributeForParentNode).getName();
        }));

        addProduction(false,new Production(0, CTokenType.VAR_LIST.ordinal(), Arrays.asList(CTokenType.PARAM_DECLARATION.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.VAR_LIST.ordinal(), Arrays.asList(CTokenType.VAR_LIST.ordinal(),CTokenType.COMMA.ordinal(),CTokenType.PARAM_DECLARATION.ordinal()),number++,v->{
            Symbol currentSym = (Symbol)parser.attributeForParentNode;
            Symbol lastSym = (Symbol)parser.valueStack.get(parser.valueStack.size() - 3);
            currentSym.setNext(lastSym);
        }));

        TYPE_NT_VAR_DECL_TO_PARAM_DECLARATION = number;
        addProduction(false,new Production(0, CTokenType.PARAM_DECLARATION.ordinal(), Arrays.asList(CTokenType.TYPE_NT.ordinal(),CTokenType.VAR_DECL.ordinal()),number++,v->{
            Symbol symbol = (Symbol)parser.attributeForParentNode;

            TypeLink specifier = (TypeLink)(parser.valueStack.get(parser.valueStack.size() - 2));

            typeSystem.addSpecifier(symbol,specifier);
            typeSystem.addSymbol(symbol, parser.scope);
        }));

        addProduction(false,new Production(0, CTokenType.TYPE_NT.ordinal(), Arrays.asList(CTokenType.TYPE_SPECIFIER.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.TYPE_NT.ordinal(), Arrays.asList(CTokenType.TYPE.ordinal(),CTokenType.TYPE_SPECIFIER.ordinal()),number++));
    }

    public static int TYPE_NT_VAR_DECL_TO_PARAM_DECLARATION;
    public static int NEW_NAME_LP_RP_TO_FUNCT_DECL;
    public static int NEW_NAME_LP_VAR_LIST_RP_TO_FUNCT_DECL;

    private void setFunctionSymbol(boolean hasArgs) {
        Symbol funcSymbol = null;
        if (hasArgs) {
            funcSymbol = (Symbol)parser.valueStack.get(parser.valueStack.size() - 4);
        } else {
            funcSymbol = (Symbol)parser.valueStack.get(parser.valueStack.size() - 3);
        }
        typeSystem.addDeclarator(funcSymbol, Declarator.FUNCTION);
        parser.attributeForParentNode = funcSymbol;
    }
    /**
     * production number begin from 23
     * 结构体定义
     *
     * TYPE_SPECIFIER -> STRUCT_SPECIFIER
     * STRUCT_SPECIFIER -> STRUCT OPT_TAG LC DEF_LIST RC
     *                     | STRUCT TAG
     * OPT_TAG -> TAG
     *
     * TAG -> NAME
     *
     * DEF_LIST ->  DEF
     * DEF_LIST ->  DEF_LIST DEF
     *
     *
     * DEF -> SPECIFIERS  DECL_LIST SEMI
     *        | SPECIFIERS SEMI
     *
     *
     * DECL_LIST -> DECL
     *             | DECL_LIST COMMA DECL
     *
     * DECL -> VAR_DECL
     *
     * VAR_DECL -> NEW_NAME
     *             | VAR_DECL LP RP
     *             | VAR_DECL LP VAR_LIST RP
     *             | LP VAR_DECL RP
     *             | STAR VAR_DECL
     *
     * UNARY -> UNARY STRUCTOP NAME  (a = tag->name)
     */
    private void initStructGrammar(){
        addProduction(false,new Production(0, CTokenType.TYPE_SPECIFIER.ordinal(), Arrays.asList(CTokenType.STRUCT_SPECIFIER.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.STRUCT_SPECIFIER.ordinal(), Arrays.asList(CTokenType.STRUCT.ordinal(),CTokenType.OPT_TAG.ordinal(),CTokenType.LC.ordinal(),CTokenType.DEF_LIST.ordinal(),CTokenType.RC.ordinal()),number++,v->{
            Symbol defList = (Symbol)parser.valueStack.get(parser.valueStack.size() - 2);
            StructDefine structObj = (StructDefine)parser.valueStack.get(parser.valueStack.size() - 4);
            structObj.setFields(defList);
            parser.attributeForParentNode = structObj;
            //结构体定义结束后，接下来的变量作用范围应该改为global
            parser.scope = Symbol.SCOPE;
        }));
        addProduction(false,new Production(0, CTokenType.STRUCT_SPECIFIER.ordinal(), Arrays.asList(CTokenType.STRUCT.ordinal(),CTokenType.TAG.ordinal()),number++));
        addProduction(true,new Production(0, CTokenType.OPT_TAG.ordinal(), Arrays.asList(CTokenType.TAG.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.TAG.ordinal(), Arrays.asList(CTokenType.NAME.ordinal()),number++,v->{
            parser.scope = parser.text;
            parser.attributeForParentNode = typeSystem.getStruct(parser.text);
            if (parser.attributeForParentNode == null) {
                parser.attributeForParentNode = new StructDefine(parser.text, parser.nestingLevel, null);
                typeSystem.addStruct((StructDefine)parser.attributeForParentNode);
            }
        }));
        addProduction(false,new Production(0, CTokenType.DEF_LIST.ordinal(), Arrays.asList(CTokenType.DEF.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.DEF_LIST.ordinal(), Arrays.asList(CTokenType.DEF_LIST.ordinal(),CTokenType.DEF.ordinal()),number++,v->{
            Symbol currentSym = (Symbol)parser.attributeForParentNode;
            Symbol lastSym = (Symbol)parser.valueStack.get(parser.valueStack.size() - 2);;
            currentSym.setNext(lastSym);
        }));

        SPECIFIERS_DECL_LIST_TO_DEF = number;
        addProduction(false,new Production(0, CTokenType.DEF.ordinal(), Arrays.asList(CTokenType.SPECIFIERS.ordinal(),CTokenType.DECL_LIST.ordinal(),CTokenType.SEMI.ordinal()),number++,v->{
            Symbol symbol = (Symbol)parser.attributeForParentNode;
            TypeLink specifier = (TypeLink)(parser.valueStack.get(parser.valueStack.size() - 3));
            typeSystem.addSpecifier(symbol,specifier);
            typeSystem.addSymbol(symbol, parser.scope);
        }));
        addProduction(false,new Production(0, CTokenType.DEF.ordinal(), Arrays.asList(CTokenType.SPECIFIERS.ordinal(),CTokenType.SEMI.ordinal()),number++));

        DECL_TO_DECL_LIST = number;
        addProduction(false,new Production(0, CTokenType.DECL_LIST.ordinal(), Arrays.asList(CTokenType.DECL.ordinal()),number++));

        DECL_LIST_COMMA_DECL_TO_DECL_LIST = number;
        addProduction(false,new Production(0, CTokenType.DECL_LIST.ordinal(), Arrays.asList(CTokenType.DECL_LIST.ordinal(),CTokenType.COMMA.ordinal(),CTokenType.DECL.ordinal()),number++,v->{
            Symbol currentSym = (Symbol)parser.attributeForParentNode;
            Symbol lastSym = (Symbol)parser.valueStack.get(parser.valueStack.size() - 3);
            currentSym.setNext(lastSym);
        }));
        addProduction(false,new Production(0, CTokenType.DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.NEW_NAME.ordinal()),number++));

        //这两条和函数的语法有冲突，故暂时注释，削弱了结构体部分语法功能 todo
//        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal(),CTokenType.LP.ordinal(),CTokenType.RP.ordinal()),number++));
//        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal(),CTokenType.LP.ordinal(),CTokenType.VAR_LIST.ordinal(),CTokenType.RP.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.LP.ordinal(),CTokenType.VAR_DECL.ordinal(),CTokenType.RP.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.STAR.ordinal(),CTokenType.VAR_DECL.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.STRUCTOP.ordinal(),CTokenType.NAME.ordinal()),number++));
    }

    /**
     * EXT_DEF -> OPT_SPECIFIERS FUNCT_DECL COMPOUND_STMT
     * COMPOUND_STMT-> LC RC
     * COMPOUND_STMT-> LC STMT_LIST RC
     * COMPOUND_STMT-> LC LOCAL_DEFS STMT_LIST RC
     * LOCAL_DEFS -> DEF_LIST
     * EXPR -> NO_COMMA_EXPR
     * NO_COMMA_EXPR -> NO_COMMA_EXPR EQUAL NO_COMMA_EXPR
     * NO_COMMA_EXPR -> NO_COMMA_EXPR QUEST  NO_COMMA_EXPR COLON NO_COMMA_EXPR
     * NO_COMMA_EXPR -> BINARY
     * BINARY -> UNARY
     * UNARY -> NUMBER
     * UNARY -> FALSE
     * UNARY -> TRUE
     * UNARY -> NAME
     * UNARY -> STRING
     * UNARY -> LP EXPR RP
     * STMT_LIST -> STMT_LIST STATEMENT |EMPTY
     * STMT_LIST ->  STATEMENT |EMPTY
     * STATEMENT -> EXPR SEMI
     * STATEMENT -> RETURN EXPR SEMI
     * STATEMENT -> RETURN SEMI
     * STATEMENT -> LOCAL_DEFS
     * BINARY -> BINARY RELOP BINARY  (>,>=,<,<=,==,!=)
     *
     * 函数调用
     * UNARY -> UNARY  LP ARGS RP  fun(a, b ,c)
     * UNARY -> UNARY LP RP  fun()
     * ARGS -> NO_COMMA_EXPR
     * ARGS -> NO_COMMA_EXPR COMMA ARGS
     */
    private void initFuncGrammar() {
        //函数实现
        OPT_SPECIFIERS_FUNCT_DECL_COMPOUND_STMT_TO_EXT_DEF = number;
        addProduction(false,new Production(0, CTokenType.EXT_DEF.ordinal(), Arrays.asList(CTokenType.OPT_SPECIFIERS.ordinal(),CTokenType.FUNCT_DECL.ordinal(),CTokenType.COMPOUND_STMT.ordinal()),number++,v->{
            Symbol symbol = (Symbol)parser.valueStack.get(parser.valueStack.size() - 2);
            TypeLink specifier = (TypeLink)(parser.valueStack.get(parser.valueStack.size() - 3));
            typeSystem.addSpecifier(symbol,specifier);
            //函数定义结束后，接下来的变量作用范围应该改为global
            parser.scope = Symbol.SCOPE;
        }));
        addProduction(false,new Production(0, CTokenType.COMPOUND_STMT.ordinal(), Arrays.asList(CTokenType.LC.ordinal(),CTokenType.RC.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.COMPOUND_STMT.ordinal(), Arrays.asList(CTokenType.LC.ordinal(),CTokenType.STMT_LIST.ordinal(),CTokenType.RC.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.COMPOUND_STMT.ordinal(), Arrays.asList(CTokenType.LC.ordinal(),CTokenType.LOCAL_DEFS.ordinal(),CTokenType.STMT_LIST.ordinal(),CTokenType.RC.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.LOCAL_DEFS.ordinal(), Arrays.asList(CTokenType.DEF_LIST.ordinal()),number++));

        NoCommaExpr_TO_Expr = number;
        addProduction(false,new Production(0, CTokenType.EXPR.ordinal(), Arrays.asList(CTokenType.NO_COMMA_EXPR.ordinal()),number++));

        NoCommaExpr_Equal_NoCommaExpr_TO_NoCommaExpr = number;
        addProduction(false,new Production(0, CTokenType.NO_COMMA_EXPR.ordinal(), Arrays.asList(CTokenType.NO_COMMA_EXPR.ordinal(),CTokenType.EQUAL.ordinal(),CTokenType.NO_COMMA_EXPR.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.NO_COMMA_EXPR.ordinal(), Arrays.asList(CTokenType.NO_COMMA_EXPR.ordinal(),CTokenType.QUEST.ordinal(),CTokenType.NO_COMMA_EXPR.ordinal(),CTokenType.COLON.ordinal(),CTokenType.NO_COMMA_EXPR.ordinal()),number++));

        Binary_TO_NoCommaExpr = number;
        addProduction(false,new Production(0, CTokenType.NO_COMMA_EXPR.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal()),number++));

        Unary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal()),number++));

        Number_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.NUMBER.ordinal()),number++,v->{
            parser.attributeForParentNode = Integer.valueOf(parser.text);
        }));

        FALSE_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.FALSE.ordinal()),number++,v->{
            parser.attributeForParentNode = parser.text;
        }));

        TRUE_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.TRUE.ordinal()),number++,v->{
            parser.attributeForParentNode = parser.text;
        }));

        Name_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.NAME.ordinal()),number++,v->{
            parser.attributeForParentNode = typeSystem.getSymbolByText(parser.text, parser.nestingLevel, parser.scope);
        }));

        String_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.STRING.ordinal()),number++));

        LP_EXPR_RP_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.LP.ordinal(),CTokenType.EXPR.ordinal(),CTokenType.RP.ordinal()),number++));

        StmtList_Statement_TO_StmtList = number;
        addProduction(true,new Production(0, CTokenType.STMT_LIST.ordinal(), Arrays.asList(CTokenType.STMT_LIST.ordinal(),CTokenType.STATEMENT.ordinal()),number++));

        Statement_TO_StmtList = number;
        addProduction(true,new Production(0, CTokenType.STMT_LIST.ordinal(), Arrays.asList(CTokenType.STATEMENT.ordinal()),number++));

        Expr_Semi_TO_Statement = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.EXPR.ordinal(),CTokenType.SEMI.ordinal()),number++));

        RETURN_EXPR_SEMI_TO_STAT = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.RETURN.ordinal(),CTokenType.EXPR.ordinal(),CTokenType.SEMI.ordinal()),number++));

        RETURN_SEMI_TO_STAT = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.RETURN.ordinal(),CTokenType.SEMI.ordinal()),number++));

        LocalDefs_TO_Statement = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.LOCAL_DEFS.ordinal()),number++));

        Binary_RelOP_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.RELOP.ordinal(),CTokenType.BINARY.ordinal()),number++));

        UNARY_LP_ARGS_RP_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.LP.ordinal(),CTokenType.ARGS.ordinal(),CTokenType.RP.ordinal()),number++));

        UNARY_LP_RP_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.LP.ordinal(),CTokenType.RP.ordinal()),number++));

        NO_COMMA_EXPR_TO_ARGS = number;
        addProduction(false,new Production(0, CTokenType.ARGS.ordinal(), Arrays.asList(CTokenType.NO_COMMA_EXPR.ordinal()),number++));

        NO_COMMA_EXPR_COMMA_ARGS_TO_ARGS = number;
        addProduction(false,new Production(0, CTokenType.ARGS.ordinal(), Arrays.asList(CTokenType.NO_COMMA_EXPR.ordinal(),CTokenType.COMMA.ordinal(),CTokenType.ARGS.ordinal()),number++));
    }

    public static int OPT_SPECIFIERS_FUNCT_DECL_COMPOUND_STMT_TO_EXT_DEF;
    public static int UNARY_LP_RP_TO_UNARY;
    public static int NO_COMMA_EXPR_TO_ARGS;
    public static int NO_COMMA_EXPR_COMMA_ARGS_TO_ARGS;
    public static int UNARY_LP_ARGS_RP_TO_UNARY;
    public static int RETURN_EXPR_SEMI_TO_STAT;
    public static int RETURN_SEMI_TO_STAT;


    /**
     * 计算语法
     * BINARY -> BINARY STAR BINARY
     * BINARY -> BINARY DIVOP BINARY
     * BINARY -> BINARY MOD BINARY
     * BINARY -> BINARY SHIFTOP BINARY
     * BINARY -> BINARY AND BINARY
     * BINARY -> BINARY OR BINARY
     * BINARY -> BINARY XOR BINARY
     * BINARY -> BINARY PLUS BINARY
     * BINARY -> BINARY MINUS BINARY
     * BINARY -> BINARY ANDAND BINARY
     * BINARY -> BINARY OROR BINARY
     * BINARY -> NOT BINARY
     *
     * UNARY -> UNARY INCOP i++
     * UNARY -> INCOP UNARY ++i
     * UNARY -> UNARY DECOP i--
     * UNARY -> DECOP UNARY --i
     * UNARY -> MINUS UNARY  a = -a
     * UNARY -> STAR UNARY b = *a
     *
     * UNARY -> UNARY COMPOUND_ASSIGN UNARY b*=a
     */
    private void initComputeGrammar(){
        Binary_Star_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.STAR.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_Divop_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.DIVOP.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_Mod_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.MOD.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_LShiftOp_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.LSHIFTOP.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_RShiftOp_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.RSHIFTOP.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_And_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.AND.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_OR_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.OR.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_XOR_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.XOR.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_Plus_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.PLUS.ordinal(),CTokenType.BINARY.ordinal()),number++));

        Binary_Minus_Binary_TO_Binary = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.MINUS.ordinal(),CTokenType.BINARY.ordinal()),number++));

        BINARY_ANDAND_BINARY_TO_BINARY = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.ANDAND.ordinal(),CTokenType.BINARY.ordinal()),number++));

        BINARY_OROR_BINARY_TO_BINARY = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.BINARY.ordinal(),CTokenType.OROR.ordinal(),CTokenType.BINARY.ordinal()),number++));

        NOT_BINARY_TO_BINARY = number;
        addProduction(false,new Production(0, CTokenType.BINARY.ordinal(), Arrays.asList(CTokenType.NOT.ordinal(),CTokenType.BINARY.ordinal()),number++));

        UNARY_INCOP_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.INCOP.ordinal()),number++));

        INCOP_UNARY_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.INCOP.ordinal(),CTokenType.UNARY.ordinal()),number++));

        UNARY_DECOP_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.DECOP.ordinal()),number++));

        DECOP_UNARY_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.DECOP.ordinal(),CTokenType.UNARY.ordinal()),number++));

        MINUS_UNARY_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.MINUS.ordinal(),CTokenType.UNARY.ordinal()),number++));

        STAR_UNARY_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.STAR.ordinal(),CTokenType.UNARY.ordinal()),number++));

        UNARY_COMPOUND_ASSIGN_UNARY_TO_UNARY = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.COMPOUND_ASSIGN.ordinal(),CTokenType.UNARY.ordinal()),number++));
    }

    public static int BINARY_OROR_BINARY_TO_BINARY;
    public static int BINARY_ANDAND_BINARY_TO_BINARY;
    public static int NOT_BINARY_TO_BINARY;
    public static int UNARY_COMPOUND_ASSIGN_UNARY_TO_UNARY;
    public static int UNARY_INCOP_TO_UNARY;
    public static int INCOP_UNARY_TO_UNARY;
    public static int UNARY_DECOP_TO_UNARY;
    public static int DECOP_UNARY_TO_UNARY;
    public static int MINUS_UNARY_TO_UNARY;
    public static int STAR_UNARY_TO_UNARY;

    /**
     * 数组语法
     * UNARY -> UNARY LB EXPR RB (b = a[2] 使用)
     * VAR_DECL -> VAR_DECL LB CONST_EXPR RB  (a[5]  定义)
     * CONST_EXPR -> NUMBER
     */
    private void initArrayGrammar(){
        Unary_LB_Expr_RB_TO_Unary = number;
        addProduction(false,new Production(0, CTokenType.UNARY.ordinal(), Arrays.asList(CTokenType.UNARY.ordinal(),CTokenType.LB.ordinal(),CTokenType.EXPR.ordinal(),CTokenType.RB.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.VAR_DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal(),CTokenType.LB.ordinal(),CTokenType.CONST_EXPR.ordinal(),CTokenType.RB.ordinal()),number++,v->{
            //数组定义
            Declarator declarator = typeSystem.addDeclarator((Symbol)parser.valueStack.get(parser.valueStack.size() - 4), Declarator.ARRAY);
            int arrayNum = (Integer)parser.attributeForParentNode;
            declarator.setElementNum(arrayNum);
            parser.attributeForParentNode = parser.valueStack.get(parser.valueStack.size() - 4);
        }));
        addProduction(false,new Production(0, CTokenType.CONST_EXPR.ordinal(), Arrays.asList(CTokenType.NUMBER.ordinal()),number++,v->{
            parser.attributeForParentNode = Integer.valueOf(parser.text);
        }));
    }


    /**
     * goto语法
     * STATEMENT -> TARGET COLON STATEMENT
     * STATEMENT -> GOTO TARGET SEMI
     * TARGET -> NAME
     */
    private void initGotoGrammar(){
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.TARGET.ordinal(),CTokenType.COLON.ordinal(),CTokenType.STATEMENT.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.GOTO.ordinal(),CTokenType.TARGET.ordinal(),CTokenType.SEMI.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.TARGET.ordinal(), Arrays.asList(CTokenType.NAME.ordinal()),number++));
    }


    /**
     *
     * if else语法
     *
     * STATEMENT -> COMPOUND_STMT ({语句段})
     * IF_STATEMENT -> IF LP TEST RP STATEMENT
     * IF_ELSE_STATEMENT -> IF_STATEMENT
     * IF_ELSE_STATEMENT ->IF_ELSE_STATEMENT ELSE STATEMENT
     * STATEMENT -> IF_ELSE_STATEMENT
     * TEST -> EXPR
     * DECL -> VAR_DECL EQUAL INITIALIZER
     * INITIALIZER -> EXPR
     */
    private void initIfGrammar() {
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.COMPOUND_STMT.ordinal()),number++));

        If_Test_Statement_TO_IFStatement = number;
        addProduction(false,new Production(0, CTokenType.IF_STATEMENT.ordinal(), Arrays.asList(CTokenType.IF.ordinal(),CTokenType.LP.ordinal(),CTokenType.TEST.ordinal(),CTokenType.RP.ordinal(),CTokenType.STATEMENT.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.IF_ELSE_STATEMENT.ordinal(), Arrays.asList(CTokenType.IF_STATEMENT.ordinal()),number++));

        IfElseStatement_Else_Statement_TO_IfElseStatement = number;
        addProduction(false,new Production(0, CTokenType.IF_ELSE_STATEMENT.ordinal(), Arrays.asList(CTokenType.IF_ELSE_STATEMENT.ordinal(),CTokenType.ELSE.ordinal(),CTokenType.STATEMENT.ordinal()),number++));

        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.IF_ELSE_STATEMENT.ordinal()),number++));

        Expr_TO_Test = number;
        addProduction(false,new Production(0, CTokenType.TEST.ordinal(), Arrays.asList(CTokenType.EXPR.ordinal()),number++));

        Var_Decl_Init_To_Decl = number;
        addProduction(false,new Production(0, CTokenType.DECL.ordinal(), Arrays.asList(CTokenType.VAR_DECL.ordinal(),CTokenType.EQUAL.ordinal(),CTokenType.INITIALIZER.ordinal()),number++,v->{
            Symbol symbol = (Symbol) parser.valueStack.get(parser.valueStack.size() - 3);
            //函数定义变量初始化 int a=1,b=2;
//            symbol.setValue(parser.valueStack.peek());
            parser.attributeForParentNode = symbol;
        }));
        addProduction(false,new Production(0, CTokenType.INITIALIZER.ordinal(), Arrays.asList(CTokenType.EXPR.ordinal()),number++));
    }

    /**
     * for while do while语法
     *
     * STATEMENT -> WHILE LP TEST RP STATEMENT
     * STATEMENT -> FOR LP OPT_EXPR  TEST SEMI END_OPT_EXPR RP STATEMENT
     * OPT_EXPR -> EXPR SEMI
     * OPT_EXPR -> SEMI
     * END_OPT_EXPR -> EXPR
     * STATEMENT -> DO STATEMENT WHILE LP TEST RP SEMI
     */
    private void initLoopGrammar() {

        WHILE_TEST_STAT_TO_STAT = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.WHILE.ordinal(),CTokenType.LP.ordinal(),CTokenType.TEST.ordinal(),CTokenType.RP.ordinal(),CTokenType.STATEMENT.ordinal()),number++));

        FOR_OPTEXPR_TEST_ENDOPTEXPR_STAT_TO_STAT = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.FOR.ordinal(),CTokenType.LP.ordinal(),CTokenType.OPT_EXPR.ordinal(),CTokenType.TEST.ordinal()
                ,CTokenType.SEMI.ordinal(),CTokenType.END_OPT_EXPR.ordinal(),CTokenType.RP.ordinal(),CTokenType.STATEMENT.ordinal()),number++));

        EXPR_SEMI_TO_OPTEXPR = number;
        addProduction(false,new Production(0, CTokenType.OPT_EXPR.ordinal(), Arrays.asList(CTokenType.EXPR.ordinal(),CTokenType.SEMI.ordinal()),number++));

        SEMI_TO_OPTEXPR = number;
        addProduction(false,new Production(0, CTokenType.OPT_EXPR.ordinal(), Arrays.asList(CTokenType.SEMI.ordinal()),number++));

        EXPR_TO_ENDOPTEXPR = number;
        addProduction(false,new Production(0, CTokenType.END_OPT_EXPR.ordinal(), Arrays.asList(CTokenType.EXPR.ordinal()),number++));

        DO_STAT_WHILE_TEST_TO_STAT = number;
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.DO.ordinal(),CTokenType.STATEMENT.ordinal(),CTokenType.WHILE.ordinal(),CTokenType.LP.ordinal()
                ,CTokenType.TEST.ordinal(),CTokenType.RP.ordinal(),CTokenType.SEMI.ordinal()),number++));
    }

    public static int FOR_OPTEXPR_TEST_ENDOPTEXPR_STAT_TO_STAT;
    public static int EXPR_SEMI_TO_OPTEXPR;
    public static int SEMI_TO_OPTEXPR;
    public static int EXPR_TO_ENDOPTEXPR;
    public static int WHILE_TEST_STAT_TO_STAT;
    public static int DO_STAT_WHILE_TEST_TO_STAT;
    /**
     * switch case语法
     *
     * STATEMENT -> SWITCH LP EXPR RP COMPOUND_STMT
     * STATEMENT -> CASE CONST_EXPR COLON
     * STATEMENT -> DEFAULT COLON
     * STATEMENT -> BREAK SEMI;
     */
    private void initSwitchGrammar() {
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.SWITCH.ordinal(),CTokenType.LP.ordinal(),CTokenType.EXPR.ordinal(),CTokenType.RP.ordinal(),CTokenType.COMPOUND_STMT.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.CASE.ordinal(),CTokenType.CONST_EXPR.ordinal(),CTokenType.COLON.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.DEFAULT.ordinal(),CTokenType.COLON.ordinal()),number++));
        addProduction(false,new Production(0, CTokenType.STATEMENT.ordinal(), Arrays.asList(CTokenType.BREAK.ordinal(),CTokenType.SEMI.ordinal()),number++));
    }

    private void addProduction(boolean nullable, Production production){

        productionMap.compute(production.getLeft(),(k,v)->{
            if(null==v){
                v = new ArrayList<>();
            }
            if(!v.contains(production)){
                v.add(production);
            }
            return v;
        });

        addSymbolMap(nullable,production);
    }

    private void addSymbolMap(boolean nullable, Production production){
        symbolMap.compute(production.getLeft(),(k,v)->{
            if(v==null){
                v = new Symbols(k,nullable);
            }
            v.addProduction(production.getRights());
            return v;
        });
    }

    private void addTerminal(){
        for (int symbol = CTokenType.FIRST_TERMINAL_INDEX; symbol <= CTokenType.LAST_TERMINAL_INDEX; symbol++) {
            symbolMap.put(symbol, new Symbols(symbol, false));
        }
    }

    public Map<Integer, List<Production>> getProductionMap() {
        return productionMap;
    }


    public Map<Integer, Symbols> getSymbolMap() {
        return symbolMap;
    }

    public static Grammar getSelf(){
        if(null==self){
            self = new Grammar();
        }
        return self;
    }


}
